#include <fermat/dio/serving_queue_1q.h>
#include <fermat/dio/serving_request.h>

namespace fermat {


ServingQueue1Q::ServingQueue1Q():_stats(NOT_RUNNING)
{
	
}

bool ServingQueue1Q::start()
{
	_th = new Thread();
	_th->start(std::bind(&ServingQueue1Q::work, this));
	_stats.waitFor(RUNNING);
	return true;
}
ServingQueue1Q::~ServingQueue1Q()
{
	stop();
}

bool ServingQueue1Q::stop()
{
	if(_stats.get() != RUNNING) {
		return true;
	}
	_stats.setTo(TERMINATING);
	_th->join();
	delete _th;
	_th = NULL;
	_stats.waitFor(TERMINATED);
	return true;
}
void ServingQueue1Q::AddRequest(RequestPtr& req)
{
	if(!req) {
		return;
	}
	if(_stats.get() != RUNNING) {
		return;
	}
	if (!dynamic_cast<ServingRequest*>(req.get())) {
		return;
	}
	_queue.put(req);
	
}

bool ServingQueue1Q::CancelRequest(RequestPtr& req)
{
	if(!req) {
		return false;
	}
	if(_stats.get() != RUNNING) {
		return false;
	}
	if (!dynamic_cast<ServingRequest*>(req.get())) {
		return false;
	}
	bool still_in = false;
	{
		still_in = _queue.erase(req);
	}
	return still_in;
	
}
void ServingQueue1Q::work()
{
	_stats.setTo(RUNNING);
	
	for(;;) {
	
		RequestPtr req = _queue.takeTimeOut(1000);
		if(req) {
			dynamic_cast<ServingRequest*>(req.get())->serve();
		}
		if(_stats.get() == TERMINATING) {
			if(_queue.size()) {
				continue;
			} 
			break;
		}
	}
	_stats.setTo(TERMINATED);
}


}


